package main

import (
	"fmt"

	"./pkg"
)

//1.函数无需前置声明 2.不支持命名嵌套定义,但是可以匿名嵌套定义 3.具备相同签名的函数才是同一类型，参数和返回值都相同
func main() {
	sayHello()
	sayHello2(2) //与第一个不是同一类型
	sayHello3()  //与第一个是同一类型

	a := sayHello
	b := sayHello3
	a = b
	a()
	if a == nil { //函数只可以判断它是否为空，不能做其他判断
		fmt.Println("nil")
	}

	var a1 = sayHello4()
	fmt.Println(&a1, a1)

	pkg.Simile()
}

func sayHello() /*error*/ { //go语言的返回值写在函数名称后面
	fmt.Println("hello!")

	//func() aa() {} 函数内部命名嵌套定义，这样是错误的
	a := func() { fmt.Println("111") } // 匿名嵌套定义是可以的
	a()
}

func sayHello2(b int) {
	fmt.Println("hello!")

	//func() aa() {} 函数内部命名嵌套定义，这样是错误的
	a := func() { fmt.Println("222") } // 匿名嵌套定义是可以的
	a()
}

func sayHello3() {
	fmt.Println("hello!")

	//func() aa() {} 函数内部命名嵌套定义，这样是错误的
	a := func() { fmt.Println("333") } // 匿名嵌套定义是可以的
	a()
}

/*func sayHello4() {
	a:=100 //栈、堆。函数内部普通的变量就是栈，短时间存在，函数结束栈就没了，或者说线程结束，这个栈就没了。堆是永久的，程序不结束，堆就一直存在
	//return a    函数结束，局部变量的空间就被回收了，所以这里无法返回a的值或者地址
}*/

func sayHello4() int {
	a := 100 //在go语言中 当返回值是局部变量时，会将栈加入到堆中，这样再调用改函数时就不会出现因为栈的消失而无法使用
	return a
}
